import static org.junit.Assert.*;

import org.junit.Before;
import org.junit.Test;

/**
 * This class contains JUnit test methods for the ChainingHashTable class
 * 
 * 
 * @author Ray DeCuir
 * @version 1.0
 *
 */

public class ChainingHashTableTest {

	// the ChainingHashTable to be used in all of the tests
	private ChainingHashTable<Integer, String> table;
	
	
	/**
	 * This method creates a new ChainingHashTable before each test
	 * 
	 * @throws Exception Setup has failed
	 */
	@Before
	public void setUp() throws Exception 
	{
		table = new ChainingHashTable<Integer,String>(10, .5);
	}
	
	/**
	 * This test tests the insert functionality for the hash table
	 * 
	 */
	@Test
	public void testInsert()
	{
		assertTrue("Table is not empty on start",  table.isEmpty() );
		table.insert(10, "Ten");
		assertFalse( "Table is empty after adding", table.isEmpty() );
		assertEquals( "initial collisions not 0", 0, table.collisions() );
		assertTrue( "Element was not removed correctly", table.remove(10) );
		assertTrue("Table is not empty after removing all elements",  table.isEmpty() );
		assertTrue( table.size() == 0);
		for ( int i = 0 ; i < 20 ; i++)
		{
			table.insert(i, "String");
		}
		assertEquals( "collisions not 0", 0, table.collisions() );
		assertTrue( table.size() == 20);		
	}
	
	
	/**
	 * 
	 * Tests the remove functionality for the chaining hash table 
	 */
	@Test
	public void testRemove()
	{
		assertTrue("Table is not empty on start",  table.isEmpty() );
		assertEquals( "initial collisions not 0", 0, table.collisions() );
		for ( int i = 0 ; i < 4 ; i++)
		{
			table.insert(i, "String");
			table.insert(i + 10, "String2");
		}
		assertEquals( "initial collisions not 4", 4, table.collisions() );
		assertTrue( table.size() == 8);
		assertTrue( table.regrowCount() == 0);
		assertFalse("Table removed a non existing element", table.remove(35) );
		for ( int i = 0 ; i < 4 ; i++)
		{
			assertTrue( table.remove(i) );
			assertTrue( table.remove(i + 10) );
		}
		assertTrue("Table is not empty after removing all elements",  table.isEmpty() );
		assertFalse("Table removed a non existing element", table.remove(2) );
		assertTrue( table.regrowCount() == 0);
	}
	
	
	/**
	 * 
	 * Tests the re-grow methods for the chaining hash table
	 */
	@Test
	public void testRegrow()
	{
		assertTrue("Table is not empty on start",  table.isEmpty() );
		assertEquals( "initial collisions not 0", 0, table.collisions() );
		assertTrue( table.regrowCount() == 0);
		for ( int i = 0 ; i < 20 ; i++)
		{
			table.insert(i, "String");
		}
		assertEquals( "collisions not 0", 0, table.collisions() );
		assertTrue( table.size() == 20);	
		assertTrue("Table did not regrow twice", table.regrowCount() == 2 );
		table.remove(10);
		table.insert(10, "Test");
		assertTrue( table.size() == 20);
		assertTrue("Table should not have regrown here", table.regrowCount() == 2 );
	}
	
	/**
	 * 
	 * Tests the lookup functionality for the chaining hash table
	 */
	@Test
	public void testLookup()
	{
		assertTrue("Table is not empty on start",  table.isEmpty() );
		assertEquals( "initial collisions not 0", 0, table.collisions() );
		assertTrue( table.regrowCount() == 0);
		for ( int i = 0 ; i < 20 ; i++)
		{
			table.insert(i, "String" + i);
		}
		assertEquals( "collisions not 0", 0, table.collisions() );
		assertTrue( table.size() == 20);	
		assertTrue( "Looked up the wrong value", table.lookup(5).equals(  "String5") );
		assertTrue( table.remove(5) );
		assertTrue( table.size() == 19);	
		assertFalse( "Found an element that had already been deleted",  "String5".equals( table.lookup(5) ) );
		assertFalse( "Found an element that was never in the table",  "String25".equals( table.lookup(25) ) );
	}
}
